# !/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2023/9/4 15:33
# @Author : xyjiang1216
# @Email : jiangxuyan@nudt.edu.cn
# @File : transform.py
# @Version: OpenPlanner2.0

# 目标：转换成gcl
import json

from OpenPlanner.util.compute_hyper_period import compute_hyper_period


def solution_transform(solution_file,
                       stream_obj_set,
                       link_obj_set
                       ):
    # hyper_period = 10000
    hyper_period = compute_hyper_period(
        *[stream_obj.period for stream_obj in \
          stream_obj_set]
    )

    # 首先读取出每一条link的每一个数据帧
    solution = []
    with open(solution_file) as fd:
        line = fd.readline()
        while line:
            line = fd.readline()
            if "arrays at link" in line:
                link_id = line.split()[-1]
                line_index = fd.readline()
                line_index = line_index.split('|')
                win_num = len(line_index) - 3
                line = fd.readline()
                line_phi = fd.readline()
                phi_array = line_phi.split('|')[2:-1]
                line = fd.readline()
                line_tau = fd.readline()
                tau_array = line_tau.split('|')[2:-1]
                line = fd.readline()
                line_kappa = fd.readline()
                kappa_array = line_kappa.split('|')[2:-1]
                for i in range(5):
                    line = fd.readline()
                trans_window = []
                while line == '|---------------|---------------|---------------|\n':
                    line_tuple = fd.readline()
                    line = fd.readline()
                    if line_tuple != '-------------------------------------------------\n':
                        stream_id = line_tuple.split('|')[1].split()[0]
                        # print(stream_id)
                        instance_id = line_tuple.split('|')[2].split()[0]
                        omega = line_tuple.split('|')[3].split()[0]
                        trans_window.append({'stream_id': int(stream_id),
                                             'instance_id': int(instance_id),
                                             'omega': int(omega),
                                             'start': int(phi_array[int(omega)].split()[0]),
                                             'end': int(tau_array[int(omega)].split()[0]),
                                             'queue': int(kappa_array[int(omega)].split()[0])})
                solution.append({
                    'link_id': link_id,
                    'win_num': win_num,
                    'trans_window': trans_window
                })
                line = fd.readline()

    # [print(entry) for entry in solution]

    # 按照omega对链路上的window进行分类
    link_entry = []
    for entry in solution:
        trans_window = entry['trans_window']
        win_gcl = [{'start': 0,
                    'end': 0,
                    'queue': 0,
                    'stream_id': []} for i in range(entry['win_num'])]
        for stream in trans_window:
            for omega in range(entry['win_num']):
                if stream['omega'] == omega:
                    win_gcl[omega]['start'] = stream['start']
                    win_gcl[omega]['end'] = stream['end']
                    win_gcl[omega]['queue'] = stream['queue']
                    win_gcl[omega]['stream_id'].append(stream['stream_id'])
        for win_entry in win_gcl:
            win_entry['stream_id'].sort()

        link_entry.append({'link_id': entry['link_id'],
                           'win_gcl': win_gcl})

    # [print(entry) for entry in link_entry]
    solution = [{'link_id': i,
                 'gcl_entries': []} for i in range(len(link_entry))]
    for entry in link_entry:
        link_id = int(entry['link_id'])
        # st_queues = 2
        st_queues = link_obj_set[link_id].st_queues
        win_gcl = entry['win_gcl']
        init_start = 0
        new_gcl_entries = []
        for gcl_entry in win_gcl:
            start = gcl_entry['start']
            end = gcl_entry['end']
            queue = gcl_entry['queue']
            stream_id = gcl_entry['stream_id']

            if start - init_start != 0:
                dic = {"interval": start - init_start,
                       "state": '0b0'.rjust(st_queues, '0'),
                       "stream_id": 'none'}
                new_gcl_entries.append(dic)
            o_bin = bin(0b01 << queue)[2:]  # 转换为二进制，并且去掉“0b”
            out_bin = o_bin.rjust(st_queues, '0')  # 原字符串右侧对齐， 左侧补零，补齐后总位宽为8 #不带"0b"
            out_bin = "0b" + out_bin  # 带"0b"，和python内置函数bin输出格式一致，字符串开头带"0b"
            dic = {"interval": end - start,
                   "state": out_bin,
                   "stream_id": stream_id}
            new_gcl_entries.append(dic)
            init_start = end
        if init_start != hyper_period:
            dic = {"interval": hyper_period - init_start,
                   "state": "0b" + bin(0b0)[2:].rjust(st_queues, '0'),
                   "stream_id": 'none'}
            new_gcl_entries.append(dic)
        solution[link_id]['gcl_entries'] = new_gcl_entries

    json_data = json.dumps(solution, ensure_ascii=False, indent=4)

    # 将 json 数据写入文件
    # print(solution_file)
    with open(solution_file.split('.json')[0] + '_gcl.json', "w", encoding='utf-8') as file:
        file.write(json_data)


if __name__ == '__main__':
    solution_transform('temp/20230425_154508solution_demo.json')
